package com.wondersgroup.fjzlpt.org.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import com.itextpdf.tool.xml.html.CssAppliers;
import com.itextpdf.tool.xml.html.CssAppliersImpl;
import com.itextpdf.tool.xml.html.Tags;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipelineContext;
import com.quick.framework.util.LoggerUtil;

import org.apache.commons.lang.StringUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.Iterator;

/**
 * pdf文件下载工具类
 * Created by GZB on 2017/9/27.
 */
public class PdfFileUtil {

    /**
     * 重写 字符设置方法，解决中文乱码问题
     *
     */
    public static class MyFontsProvider extends XMLWorkerFontProvider {

        public MyFontsProvider(){
            super(null, null);
        }

        @Override
        public Font getFont(final String fontname, String encoding, float size, final int style) {
            String fntname = fontname;
            if (fntname == null) {
                fntname = "宋体";
            }
            if (size == 0) {
                size = 4;
            }
            return super.getFont(fntname, encoding, size, style);
        }
    }

    /**
     * 导出pdf —— 通过pdf模板
     * @param response
     * @param jsonData   pdf中需要添加的数据
     * @param modelName  使用的模板姓名（模板需要放在realPath项目文件夹中）
     * @param downFileName  下载的文件的名称（没有设置则用时间戳）
     *
     */
    public static void downLoadPdfFileByModel(HttpServletResponse response, JSONObject jsonData, String modelName,String downFileName) {
        PdfReader reader = null;
        OutputStream out = null;
        ByteArrayOutputStream bos = null;
        PdfStamper stamper = null;
        try {
            setResponseHeader(response, downFileName);
            out = response.getOutputStream();// 输出流
            reader = new PdfReader(ProjectParams.realPath + "/" + modelName);// 读取pdf模板
            bos = new ByteArrayOutputStream();
            stamper = new PdfStamper(reader, bos);
            AcroFields form = stamper.getAcroFields();
            //form.setSplitRows(true);


            //中文处理（哇哈哈哈哈）
            BaseFont bf = BaseFont.createFont("STSong-Light","UniGB-UCS2-H",BaseFont.NOT_EMBEDDED);
            Iterator<String> it = form.getFields().keySet().iterator();
            while (it.hasNext()) {
                String fieldName = it.next().toString();
                form.setFieldProperty(fieldName,"textfont",bf,null);
                form.setField(fieldName, jsonData.getString(fieldName));
            }
            stamper.setFormFlattening(true);// 如果为false那么生成的PDF文件还能编辑，一定要设为true
            stamper.close();

            Document doc = new Document();
            PdfCopy copy = new PdfCopy(doc, out);
            doc.open();
            //多页导出处理
            for(int pdfNum = 1; pdfNum <= reader.getNumberOfPages(); pdfNum++) {
                PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), pdfNum);
                copy.addPage(importPage);
            }
            doc.close();

        } catch (IOException e) {
            LoggerUtil.error(e.getMessage());
        } catch (DocumentException e) {
            LoggerUtil.error(e.getMessage());
        }finally {
            try{
                if(out != null){
                    out.close();
                }
                if(bos != null){
                    bos.close();
                }
                if(reader != null){
                    reader.close();
                }
                if(stamper != null){
                    stamper.close();
                }
            }catch (Exception e){
                LoggerUtil.error(e.getMessage());
            }
        }

    }

    /**
     * 设置response下载的pdf文件名与header设置
     * @param response
     * @throws UnsupportedEncodingException
     */
    public static void setResponseHeader(HttpServletResponse response,String downFileName) throws UnsupportedEncodingException {
        if(StringUtils.isEmpty(downFileName)){
            downFileName = System.currentTimeMillis() + ".pdf";
        }
        response.setCharacterEncoding("utf-8");
        response.setContentType("multipart/form-data");
        response.setHeader("Content-Disposition", "attachment;fileName="
                + URLEncoder.encode(downFileName, "UTF-8"));
    }

    /**
     * 导出pdf —— 通过html字符串
     * @param response
     * @param downFileName 下载的文件名称
     * @param htmlDocument 需要载入到pdf中的html代码(特别注意：该document结构中最好包含<body></body>标签)
     */
    public static void downLoadPdfFileByHtml(HttpServletResponse response, String downFileName, String htmlDocument) {
        try {
            setResponseHeader(response, downFileName);
            // step 1B4
            Document document = new Document(PageSize.A4);
            // 设置边距，单位都是像素，换算大约1厘米=28.33像素
            //document.setMargins(50, 50, 50, 50);
            // step 2
            PdfWriter writer = PdfWriter.getInstance(document, response.getOutputStream());
            // step 3
            document.open();
            InputStream htmlInput = new ByteArrayInputStream(htmlDocument.getBytes("UTF-8"));
            // 使用我们的字体提供器，并将其设置为unicode字体样式
            MyFontsProvider fontProvider = new MyFontsProvider();
            fontProvider.addFontSubstitute("lowagie", "garamond");
            fontProvider.setUseUnicode(true);
            CssAppliers cssAppliers = new CssAppliersImpl(fontProvider);
            HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
            htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
            XMLWorkerHelper.getInstance().getDefaultCssResolver(true);

            // step 4 : pdf中写入内容
            //单标签处理
            String scriptRegx =  "(?i)(<SCRIPT)[\\s\\S]*?((</SCRIPT>)|(/>))",
                    brRegx = "(?i)(</*br.*?>)",
                    tableRegx = "(?i)(<table (?!ignore=\"true\").*?>)",
                    imgRegx = "(?i)(<img\\s.*?>)",
                    linkRegx = "(?i)(<link\\s.*?>)",
                    metaRegx = "(?i)(<meta\\s.*?>)",
                    inputRegx = "(?i)(<input\\s.*?)>";
            htmlDocument = htmlDocument.replaceAll(scriptRegx, "")
//                    .replaceAll("\r|\n|\\r|\\n|\r\n|\\r\\n|\t|\\t", "")
//                    .replaceAll(imgRegx, "")
//                    .replaceAll(nbspRegx, " ")
//                    .replaceAll(linkRegx, " ")
//                    .replaceAll(metaRegx, " ")
                    .replaceAll(tableRegx, "<table style=\"width:100%;table-layout:fixed;\" cellpadding=\"5\" cellspacing=\"-1\">")
                    .replaceAll(inputRegx, "$1 />")
                    .replaceAll(brRegx, "<br/>");
            XMLWorkerHelper.getInstance().parseXHtml(writer, document,
                    new ByteArrayInputStream(htmlDocument.getBytes("UTF-8")), Charset.forName("UTF-8"));
//            XMLWorkerHelper.getInstance().parseXHtml(writer, document,
//                    htmlInput, null,Charset.forName("UTF-8"),fontProvider);
            // step 5
            document.close();
        } catch (UnsupportedEncodingException e) {
            LoggerUtil.error(e.getMessage());
            e.printStackTrace();
        }catch (IOException e) {
            LoggerUtil.error(e.getMessage());
            e.printStackTrace();
        }catch (DocumentException e) {
            LoggerUtil.error(e.getMessage());
            e.printStackTrace();
        }
    }




    //  下方测试区域  ==  下方测试区域  ==  下方测试区域
    //====================================================================
    //====================================================================
    //====================================================================
    public static void create() throws Exception {

        // html中字体非常郁闷
        // 1. html中不指定字体，则默认使用英文字体，中文会不显示。
        // 2. html中指定的字体必须是英文名称，如宋体：font-family:SimSun;
        // 3. html中不能指定自定义字体，必须指定itext支持的字体，还好itext支持字体比较多，常见操作系统带的都支持
        // 4. 暂没有找到如何html中支持自定义字体方法，网上都是修改源码实现默认字体中文，也很重要

        StringBuilder html = new StringBuilder();
        html.append("<html>");
        html.append("<body style='font-size:20px;font-family:SimSun;'>"); //style中的font-family:SimSum能处理中文乱码
        html.append("<table width='19cm'border='1' cellpadding='0' cellspacing='0'>");
        html.append("<tr>");
        html.append("<td colspan='2'>凉州词</td>");
        html.append("</tr>");
        html.append("<tr>");
        html.append("<td>黄河远上白云间，一片孤城万仞山。</td>");
        html.append("<td>羌笛何须怨杨柳，春风不度玉门关。</td>");
        html.append("</tr>");
        html.append("</table>");
        html.append("<div id=\"aabb\">还要测试</div>");
        html.append("<style>#aabb{color:red;width:100%;float:right}</style>");
        html.append("</body>");
        html.append("</html>");
        String inputRegx = "(?i)(<input\\s.*?>)";
        String htmlDocument = html.toString().replaceAll(inputRegx, "");

        InputStream is = new ByteArrayInputStream(htmlDocument.getBytes());

        OutputStream os = new FileOutputStream("D:/demo.4.pdf");
        Document document = new Document();

        PdfWriter writer = PdfWriter.getInstance(document,os);

        document.open();

        // 将html转pdf
        XMLWorkerHelper.getInstance().parseXHtml(writer,document, is);

        document.close();
    }

    public static void main(String[]args) throws Exception {
        create();
    }

}
